1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 import java.util.*;
33 import java.lang.management.*;
34 import java.lang.reflect.*;
35 import javax.management.*;
36 import javax.management.openmbean.*;
37 import com.sun.management.GarbageCollectionNotificationInfo;
38 import com.sun.management.GcInfo;
39 import java.security.AccessController;
40 import java.security.PrivilegedAction;
41 import java.lang.reflect.Field;
42
43 public class GarbageCollectionNotificationTest {
44 private static HashMap<String,Boolean> listenerInvoked = new HashMap<String,Boolean>();
45 static volatile long count = 0;
46 static volatile long number = 0;
47 static Object synchronizer = new Object();
48
49 static class GcListener implements NotificationListener {
50 public void handleNotification(Notification notif, Object handback) {
51 String type = notif.getType();
52 if (type.equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) {
53 GarbageCollectionNotificationInfo gcNotif =
54 GarbageCollectionNotificationInfo.from((CompositeData) notif.getUserData());
55 String source = ((ObjectName)notif.getSource()).getCanonicalName();
56 synchronized(synchronizer) {
57 if(!listenerInvoked.get(source)) {
58 listenerInvoked.put(((ObjectName)notif.getSource()).getCanonicalName(),true);
59 count++;
60 if(count >= number) {
61 synchronizer.notify();
62 }
63 }
64 }
65 }
66 }
67 }
68
69 public static void main(String[] args) throws Exception {
70 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
71 final Boolean isNotificationSupported = AccessController.doPrivileged (new PrivilegedAction<Boolean>() {
72 public Boolean run() {
73 try {
74 Class cl = Class.forName("sun.management.VMManagementImpl");
75 Field f = cl.getDeclaredField("gcNotificationSupport");
76 f.setAccessible(true);
77 return f.getBoolean(null);
78 } catch(ClassNotFoundException e) {
79 return false;
80 } catch(NoSuchFieldException e) {
81 return false;
82 } catch(IllegalAccessException e) {
83 return false;
84 }
85 }
86 });
87 if(!isNotificationSupported) {
88 System.out.println("GC Notification not supported by the JVM, test skipped");
89 return;
90 }
91 final ObjectName gcMXBeanPattern =
92 new ObjectName("java.lang:type=GarbageCollector,*");
93 Set<ObjectName> names =
94 mbs.queryNames(gcMXBeanPattern, null);
95 if (names.isEmpty())
96 throw new Exception("Test incorrect: no GC MXBeans");
97 number = names.size();
98 for (ObjectName n : names) {
99 if(mbs.isInstanceOf(n,"javax.management.NotificationEmitter")) {
100 listenerInvoked.put(n.getCanonicalName(),false);
101 GcListener listener = new GcListener();
102 mbs.addNotificationListener(n, listener, null, null);
103 }
104 }
105
106 System.gc();
107
108 Object data[] = new Object[32];
109 for(int i = 0; i<100000000; i++) {
110 data[i%32] = new int[8];
111 }
112 int wakeup = 0;
113 synchronized(synchronizer) {
114 while(count != number) {
115 synchronizer.wait(10000);
116 wakeup++;
117 if(wakeup > 10)
118 break;
119 }
120 }
121 for (String source : listenerInvoked.keySet()) {
122 if(!listenerInvoked.get(source))
123 throw new Exception("Test incorrect: notifications have not been sent for "
124 + source);
125 }
126 System.out.println("Test passed");
127 }
128 }